home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
embedded
/
mcu11
/
examples.arc
/
EX10
< prev
next >
Wrap
Text File
|
1988-11-29
|
27KB
|
846 lines
*****
*
* This file contains all Examples for section 10 of the User's Manual
*
*****
** Equates - Registers will be addressed with Ind,X mode
*
REGBAS EQU $1000 Starting address for register block
PORTB EQU $04 Output port B
OC1M EQU $0C OC1M7,OC1M6,OC1M5,OC1M4;OC1M3,-,-,-
OC1D EQU $0D OC1D7,OC1D6,OC1D5,OC1D4;OC1D3,-,-,-
TCNT EQU $0E Free running counter (16-bit)
TIC1 EQU $10 IC1 register (16-bit)
TOC1 EQU $16 OC1 register (16-bit)
TOC2 EQU $18 OC2 register (16-bit)
TOC3 EQU $1A OC3 register (16-bit)
TCTL1 EQU $20 OM2,OL2,OM3,OL3;OM4,OL4,OM5,OL5
TCTL2 EQU $21 -,-,EDG1B,EDG1A;EDG2B,EDG2A,EDG3B,EDG3A
TMSK1 EQU $22 OC1I,OC2I,OC3I,OC4I;OC5I,IC1I,IC2I,IC3I
TFLG1 EQU $23 OC1F,OC2F,OC3F,OC4F;OC5F,IC1F,IC2F,IC3F
TMSK2 EQU $24 TOI,RTII,PAOVI,PAII;-,-,PR1,PR0
TFLG2 EQU $25 TOF,RTIF,PAOVF,PAIF;-,-,-,-
*** EVB Routine Addresses & Pseudo Vector Equates
.OUTA EQU $FFB8 Print character in A-reg
.OUTCRL EQU $FFC4 Output <cr><lf>
.OUTSTO EQU $FFCA Output Msg seg (no <cr,lf>)
.OUTSTR EQU $FFC7 Output Msg w/ leading <cr,lf>
PVIC1 EQU $00E8 EVB Pseudo Vector for IC1
PVTOF EQU $00D0 EVB Pseudo Vector for TOF
PVOC2 EQU $00DC EVB Pseudo Vector for OC2
PVOC1 EQU $00DF EVB Pseudo Vector for OC1
*** RAM Variable Assignments
ORG $D000 Start variables in EVB RAM (upper half)
HDLY RMB 2 Half-cycle delay (in 0.5╡S increments)
PWMP1P RMB 1 1% of PWM period (1 to 256 cycles) Ex 10-7
PWMDC1 RMB 1 Duty cycle for PWM signal at OC2 pin
PWMDC2 RMB 1 Duty cycle for PWM signal at OC3 pin
IC1DUN RMB 1 flag: 0-not done,1-pulse measured
IC1MOD RMB 1 s/w mode flag: FF-off,0-1st,1-last edge
OVCNT1 RMB 1 Overflow count (upper 8-bits of result)
RES1 RMB 2 Pulse Width in cycles (16-bits)
HTEMP RMB 3 Temp for H6TOD8 (3 bytes)
FRSTE RMB 2 Time of first edge (16-bits)
PERC RMB 2 Period in cycles (16-bits)
TEMP1 RMB 2 Temp for conversion (16-bits)
FREQH RMB 2 Freq in Hex (16-bits)
HPW RMB 2 Pulse Width (16-bits hex)
DBUFR RMB 8 Decimal result buffer (8 bytes ASCII)
* Some routines use only first 5 bytes of DBUFR
PWMPER RMB 2 Period of PWM signals in (cycles)
OFFHI RMB 2 OC2 high offset (calculated)
OFFLO RMB 2 OC2 low offset (calculated)
ORG $C000 Prog starts in EVB RAM at $C000
***
* TIMER EXAMPLE 10-1a Measuring Period with Input Capture
*
* Uses polling rather than interrupts.
* Measures period between two rising edges at IC1 pin.
* Overflows not considered so max period is 65,535 cyc
* Min period measurable with this program is about 27 cyc
*
* This program runs on an EVB board and displays results
* on the EVB terminal display.
***
PERTOP LDS #$0047 Top of User's stack area on EVB
LDX #REGBAS Point to register block
LDAA #%00010000
STAA TCTL2,X EDG1B:EDG1A = 0:1, rising edges
LDAA #$04
STAA TFLG1,X Clear any old OC1 flag
* Ready to detect first rising edge
BRCLR TFLG1,X $04 * Loop here until edge
* First edge detected
LDD TIC1,X Read time of first edge
STD FRSTE Save first capture value
LDAA #$04
STAA TFLG1,X Clear IC1F before next edge
* Ready to capture time of second edge
BRCLR TFLG1,X $04 * Loop here until edge
* Second edge detected
LDD TIC1,X Read time of second edge
SUBD FRSTE 2nd - 1st -> D
STD PERC Save result (period in cycles)
* The period of the signal at the PA2/IC1 pin has been measured
* and the time is stored at "PERC" as a 16-bit hex number
* representing the number of CPU bus cycles that elapsed
* between two rising edges.
***
* TIMER EXAMPLE 10-1b Changing Period to Frequency
*
* The period found in example 10-1a is expressed as a number
* of bus cycles (@E=2MHz, 1 bus cycle=0.5╡S) and it is
* currently in the D-reg and at "PERC". Values < or = $20
* will be considered too small (freq too high) to be
* accurately measured with this program and will be trapped
* out to make the period to frequency conversion program easier.
* $0021 corresponds to 60,606 Hz, $FFFF is 30.5 Hz.
***
LDX PERC Period in cycles (16-bits)
CPD #32 ($20) Check against min allowed
BHI OKP Skip if OK
JMP OUTRNG Else go say it was too small
OKP LDD #32 X=period; D=32
FDIV D/X -> X; r -> D
STX TEMP1 (Freq*16)╓1,000,000; radix left of MSB
*
* We now have frequency but it isn't in a good displayable
* form yet. If we move the binary radix 16 places to the right
* we would have a 16-bit integer representing
* [(2**20)/(10**6) x freq] or [((1,048,576)/(1,000,000))*freq].
* By adding and subtracting binary multiples of the freq we
* will arrive at [((1,000,000)/(1,000,000))*freq]
*
* 1,048,576 16-bit starting value ((2**20)freq)╓(10**6)
* - 32,768 2**15
* - 16,384 2**14
* + 512 2**9
* + 64 2**6
* =1,000,000 * freq
*
* The limitation of 33 ($21) cycles min was selected so
* (1,048,576/1,000,000)*freq would fit in 16-bits so we would
* only need 1 FDIV. Although it is pretty easy to extend the
* precision of an FDIV.
*
* The partial results which are added and subtracted in this
* program may have an error of ▒1 LSB ea. because I trunkated
* rather than rounding.
*
LDD TEMP1 (2**20)f; where f=freq╓(10**6)
LSRD
LSRD
LSRD A=(2**9)f; D=(2**17)f
CLR FREQH Clear upper half of hex freq location
STAA FREQH+1 FREQH is a temp = 512f
LSRD
LSRD now D=(2**15)f or 32,768f
STD TEMP1 Needs to be in mem for 16-bit subtract
XGDX D=(2**20)f; X=(2**15)f
SUBD TEMP1 First subtraction (-32K)
XGDX Working result -> X; D=(2**15)f
LSRD A=(2**6)f; D=(2**14)f
STD TEMP1 Put in mem so you can subtract
ADDA FREQH+1 (512+64)f
STAA FREQH+1 Update low half of FREQH
XGDX D=1,015,808*f; X=junk
SUBD TEMP1 999,424*f
ADDD FREQH 1,000,000*f = frequency
STD FREQH Save the 16-bit binary result
*
* Since most of us don't think in hexidecimal, let's change to
* decimal before printing. The subroutine (HTODP) is shown at
* the end of this listing.
*
* The display will look like...
*
*ppppp Cyc fffff Hz ---or like---
*Freq. is too high
*
* where ppppp is period in cycles & fffff is freq. (decimal)
*
* EVB subroutines will be used and when done we will jump
* back to the beginning and repeat continuously.
*
JSR .OUTCRL Print a <cr,lf>
LDX #PERC Point at hex period
JSR HTOD Convert to 5 digit decimal
JSR P5DEC Print 5 digi decimal (not leading 0s)
LDX #MSGCYC Point at " Cycles "
JSR .OUTSTO Print message segment
LDX #FREQH Point at hex frequency
JSR HTOD Convert to 5 digit decimal
JSR P5DEC Print 5 digi decimal (not leading 0s)
LDX #MSGHZ Point at " Hz"
JSR .OUTSTO Print message segment
JTOP JMP PERTOP Go back to top & measure another period
OUTRNG LDX #MSGER1 Point at "Freq. is too high"
JSR .OUTSTR Print message w/ leading <cr,lf>
BRA JTOP Go back to top & measure another period
*
***** END Ex 10-1b
***
* TIMER EXAMPLE 10-2 Measuring Pulses With Input Capture
*
* Uses interrupts.
* Measures time between a rising edge and a falling edge
* (period of a positive pulse) at the IC1 pin.
* Overflows not considered so max is 65,536 cyc
* Min time measurable with this program is about __ cyc
*
* This program runs on an EVB board and displays results
* on the EVB terminal display.
***
* Initialization Portion
*
PWINZ LDS #$0047 Top of User's stack area on EVB
LDAA #$7E Jump (extended) Opcode
STAA PVIC1 IC1 Pseudo Vector
LDX #SV2IC1 Address of IC1 service routine
STX PVIC1+1 Finish jump instruc to IC1 routine
* Main Program Portion of Pulse Width program
*
PWTOP LDX #REGBAS Point to register block
LDAA #%00010000 Top of Main for PW24 prog
STAA TCTL2,X EDG1B:EDG1A = 0:1, IC1 rising edges
LDAA #$FF
STAA IC1MOD FF-IC1 off; 0-1st edge; 1-last edge
CLR IC1DUN Signal pulse not done
BCLR TFLG1,X $FB clear IC1F (if any)
BSET TMSK1,X $04 enable IC1 interrupts
CLI Enable Interrupts
WAITL2 LDAA IC1DUN Sets after pulse done
BEQ WAITL2 Tight loop till pulse has been timed
SEI Pulse done, disable interrupts
* Display pulse width as xx,xxx microseconds (32,768 max)
JSR .OUTCRL Begin printing result
LDD HPW number of cyc (0.5╡S/cyc)
LSRD 16-bit ╓2 to change to ╡S
BCC ARNUP2 ? need to round result ?
ADDD #1 yes; round up
ARNUP2 STD HPW Update hex Pulse width
LDX #HPW Point at hex pulse width
JSR HTOD Convert to 5 digit decimal
JSR P5DEC Print 5 digi decimal (not leading 0s)
LDX #MSGMS Point at rest of display line
JSR .OUTSTO Print " millieconds"
BRA PWTOP Goto top of main & repeat
*
* END of Main Program Portion
***
* SV2IC1 - Input Capture 1 service routine
*
* Called first when a rising edge is detected and again when
* a falling edge is detected.
***
SV2IC1 LDX #REGBAS point at top of register block
INC IC1MOD $FF->0 at 1st edge; 0->1 at 2nd
BNE NO1ST2 if not 0, this is trailing edge
* Process leading edge of pulse
LDD TIC1,X read time of first edge
STD FRSTE save till next capture
* Reconfigure IC1 for trailing falling edge
BCLR TCTL2,X $30 EDG1B:EDG1A->0:0
BSET TCTL2,X $20 EDG1B:EDG1A->1:0
BRA OU2IC1 done processing first edge
* Process trailing edge of pulse
NO1ST2 LDD TIC1,X get time of trailing edge
SUBD FRSTE time of last minus time of first
STD HPW update result
BCLR TCTL2,X $30 disable IC1
LDAA #1
STAA IC1DUN signal pulse measured
OU2IC1 BCLR TFLG1,X $FB clear IC1F
RTI ** Return from IC1 service **
*
***** END Ex 10-2
***
*
* TIMER EXAMPLE 10-3 Measuring Long Periods with IC
*
* Uses interrupts.
* Measures period between two rising edges at the IC1 pin.
* Overflows are counted so max is 16,777,215 cyc (~8.38 Sec)
* Min time measurable with this program is about 70 cyc
*
* This program runs on an EVB board and displays results
* on the EVB terminal display.
***
* Initialization Portion
*
P24INZ LDS #$0047 Top of User's stack area on EVB
LDAA #$7E Jump (extended) Opcode
STAA PVTOF TOF Pseudo Vector see manual text
STAA PVIC1 IC1 Pseudo Vector
LDX #SV3TOF Address of TOF service routine
STX PVTOF+1 Finish jump instruc to TOF routine
LDX #SV3IC1 Address of IC1 service routine
STX PVIC1+1 Finish jump instruc to IC1 routine
* Main Program Portion of PER24 program
*
PER24T LDX #REGBAS Point to register block
LDAA #%00010000 Top of Main for PER24 prog
STAA TCTL2,X EDG1B:EDG1A = 0:1, IC1 rising edges
LDAA #$FF
STAA IC1MOD FF-IC1 off; 0-1st edge; 1-last edge
CLR IC1DUN Signal period not done
BCLR TFLG1,X $FB clear IC1F (if any)
BCLR TFLG2,X $7F clear TOF (if any)
BSET TMSK1,X $04 enable IC1 interrupts
BSET TMSK2,X $80 enable TOF interrupts
CLI Enable Interrupts
WAITL3 LDAA IC1DUN Sets after pulse done
BEQ WAITL3 Tight loop till pulse has been timed
SEI Pulse done, disable interrupts
* Display period as x.xxxxxx Seconds (to nearest ╡S)
LDX #OVCNT1 Point at upper byte of 6 digit hex
LSR 0,X 24-bit ╓2 to change to ╡S
ROR 1,X (1cyc=0.5╡S)
ROR 2,X RORs include carry
BCC ARNUP3 ? need to round result ?
INC 2,X yes; round up
BNE ARNUP3 carry to middle byte ?
INC 1,X yes
BNE ARNUP3 carry to high byte ?
INC 0,X yes
ARNUP3 JSR H6TOD8 Convert to 8 digit decimal
JSR .OUTCRL Begin printing result
LDX #DBUFR+1 Start at 2nd digit (1st is 0)
LDAA 0,X Seconds digit
JSR .OUTA Print
LDAA #'.' ASCII period
JSR .OUTA Print
DUMPLP INX Advance pointer to next digt
LDAA 0,X get digit
JSR .OUTA Print it
CPX #DBUFR+7 Was that the last ?
BNE DUMPLP If not continue
LDX #MSGSEC Point at rest of display line
JSR .OUTSTO Print " Seconds"
BRA PER24T Goto top of main & repeat
*
* END of Main Program Portion
***
* SV3TOF - Timer Overflow service routine
*
* Called whenever any timer overflow is detected. If the IC1
* pulse measurement is in progress (IC1MOD positive) then
* the overflow counter (upper 8-bits of period) is incremented.
***
SV3TOF TST IC1MOD if 0 or 1, IC1 active so count TOFs
BMI OU3TOF if neg, IC1 not active
INC OVCNT1 increment IC1 overflow count
OU3TOF LDAA #$80
STAA REGBAS+TFLG2 Clear overflow flag
RTI ** Return from TOF service **
***
* SV3IC1 - Input Capture 1 service routine
*
* Called first when a rising edge is detected and again when
* another rising edge is detected.
***
SV3IC1 LDX #REGBAS point at top of register block
INC IC1MOD $FF->0 at 1st edge; 0->1 at 2nd
BNE NO1ST3 if not 0, this is second edge
* Process first edge of pulse
CLR OVCNT1 Zero the overflow count
LDD TIC1,X Read time of first edge
STD RES1 Save till next capture
BMI OU3IC1 Done if IC was before any overflow
LDAA TFLG2,X Check for TOF in MSB
BPL OU3IC1 If no overflow, you're done
DEC OVCNT1 This TOF shouldn't count
* decrement OVCNT1 to -1, TOF svc routine will inc to zero
BRA OU3IC1 Done processing first edge
* Process second edge of pulse
NO1ST3 LDD TIC1,X Get time of second edge
BMI ARNOV1 If MSB=1, skip TOF check
TST TFLG2,X Check for overflow
BPL ARNOV1 If no TOF, skip increment
INC OVCNT1 TOF was before edge so count it
ARNOV1 SUBD RES1 Time of last minus time of first
STD RES1 Update result
BCC RES1OK Check for borrow
DEC OVCNT1 If borrow, fix overflow count
RES1OK BCLR TCTL2,X $30 Disable IC1
LDAA #1
STAA IC1DUN Signal pulse measured
OU3IC1 BCLR TFLG1,X $FB Clear IC1F
RTI ** Return from IC1 service **
*
***** END Ex 10-3
***
*
* TIMER EXAMPLE 10-4 Simple Output Compare Example
*
* Ex10-4 uses polled mode.
* Generate a 10mS period like you would use to time an EE write
* but rather than wearout the EEPROM just change an output pin
*
* Example 10-4 runs on an EVB board and drives PB0 high for
* 10mS once every 30mS so you can see on an oscilloscope.
***
INZA LDX #REGBAS Point to register block
LDAA #$80
STAA TFLG1,X Clear any pending OC1F flag
CLR PORTB,X Initialize port B to zeros
TOP4A LDAA #1 Top of Ex10-4a
STAA PORTB,X Set LSB of port B
* This is where the 10mS delay part actually starts
*
LDD TCNT,X Get current timer count
ADDD #20000 What will count be in 10mS?
STD TOC1,X Set OC1 to trigger then
LP1 BRCLR TFLG1,X $80 LP1 Loop here till OC1F=1
*
*Delay is actually done here; rest is just support
BCLR TFLG1,X $7F Clear OC1F
CLR PORTB,X Clear PB0 pin
LDY #5710 5710*(7~/loop)= about 20mS
DLP1 DEY Top of software delay loop
BNE DLP1 Loop 'till Y is zero
BRA TOP4A Repeat continuously for O-scope
*
***** END Ex 10-4
***
*
* TIMER EXAMPLE 10-5 Square wave using Output Compare
*
* Ex10-5 uses interrupts.
* Generate a square wave at the PA6 output pin using OC2
*
* This program runs on an EVB board. The half-cycle delay
* time is entered into the double byte variable "HDLY" at
* $D000,D001 with a memory modify before going to the program.
***
TOP5 LDS #$0047 Top of User's stack area on EVB
LDAA #$7E Jump (extended) Opcode
STAA PVOC2 OC2 Pseudo Vector see manual text
LDX #SV5OC2 Address of OC2 service routine
STX PVOC2+1 Finish jump instruc to TOF routine
LDX #REGBAS Point to register block
LDAA #%01000000 OM2:OL2 = 0:1
STAA TCTL1,X Setup OC2 for toggle on each compare
STAA TFLG1,X Clear any pending OC2F
STAA TMSK1,X Enable OC2 interrupts
CLI Enable Interrupts
BRA * Interrupt driven; so twiddle thumbs
***
* SV5OC2 - Output Compare 2 service routine
*
* Called at each OC2 interrupt.
***
SV5OC2 LDD HDLY Get delay time for 1/2 cycle
ADDD TOC2,X Add to last compare value
STD TOC2,X Update OC2 (schedule next edge)
BCLR TFLG1,X $BF Clear OC2F
RTI ** Return from OC2 service **
*
***** END Ex 10-5
***
* TIMER EXAMPLE 10-6
* OC1, OC2, and OC3 used together to produce 2 PWM signals
*
* OC1 controls two pins of port A in conjunction with OC2 and OC3
* OC1 drives the period and the scheduling of OC2 and OC3
* OC2 & OC3 automatically control pins but don't generate interrupts
* Set "PWMP1P", "PWMDC1" & "PWMDC2" manually before running this example
* "PWMP1P" sets size of a 1% segment of PWM period (cycles)
* min PWMP1P for this program is 2 (period = 200 cycles)
* "PWMDC1" sets Duty cycle for OC2 pin in % (0 to $64 hex)
* "PWMDC2" sets Duty cycle for OC3 pin in % (0 to $64 hex)
* Duty cycle (%) will be translated into a # of cycles offset
* and period will be calculated as (100 * PWMP1P) at prog start
* PA4 pin will toggle at each OC1 compare as a scope reference signal
*
* Produces high going PWM signals of the period and duty cycle specified.
* Note actually only produces PWMs of 50% to 100% because spec'd duty of
* 0 to 50% is changed to low going PWM w/ duty cyc = [100% - spec(0-50)]
*
* This program runs on an EVB board and drives output pins.
* An oscilloscope is used to study the results.
***
INZ6 LDS #$0047 Top of User's stack area on EVB
LDAA #$7E Jump (extended) Opcode
STAA PVOC1 OC1 Pseudo Vector see manual text
LDX #SV6OC1 Address of OC1 service routine
STX PVOC1+1 Finish jump instruc to OC1 routine
LDX #REGBAS Point to register block
LDAA #%01010000 OMx:OLx = 0:1 for toggle
STAA TCTL1,X OC2 and OC3 for toggle
LDAA #%01110000 OC1M6,5, & 4 = 1
STAA OC1M,X To control OC2/PA6, OC3/PA5, & PA4
CLRB Build OC1D initial value in B
LDAA PWMDC1 Check for OC2 duty > or = 50%
CMPA #50
BLS ARNZ61 If <50% OC1 drives low, OC2 toggles high
ADDB #%01000000 else OC1 drives high, OC2 toggles low
ARNZ61 LDAA PWMDC2 Check for OC3 duty > or = 50%
CMPA #50
BLS ARNZ62 If <50% OC1 drives low, OC3 toggles high
ADDB #%00100000 else OC1 drives high, OC3 toggles low
ARNZ62 STAB OC1D,X Store starting value for OC1D
* Calculate period & duty cycle as cycle count offsets
LDAA PWMP1P 1% of period
LDAB #100
MUL 100 * PWMP1P = PWMPER
STD PWMPER Store period
STD TOC1,X Start first PWM period at TCNT=PWMPER
LDAA PWMDC1 Calculate offset for OC2
BSR CALOFF Adj duty as needed and calc offset
STD TOC2,X Schedule first OC2 toggle
LDAA PWMDC2 Calculate offset for OC3
BSR CALOFF Adj duty as needed and calc offset
STD TOC3,X Schedule first OC3 toggle
* Finish initialization
LDAA #$80
STAA TFLG1,X OC1F=1 to clear any old OC1 flag
STAA TMSK1,X then OC1I=1 to enable OC1 interrupt
CLI
BRA * From now on OC1 interrupt runs PWMs
*** Local subroutine for changing duty cycle to an offset count
* If duty < 50% ($32) change to 100-duty
* If duty >100% ($64) force to $64
* Finally mult by 1% of period (cyc)
* Enter with PWMDCx duty in A-reg, Return offset in D-reg
CALOFF CMPA #50 Check for 0-49%
BHS ARN6A Around fixup
TAB If < 50% - set to 100 - duty cycle
LDAA #100
SBA A-B to A
ARN6A CMPA #100 Check for > 100%
BLS ARN6B
LDAA #100 If > 100% - set to 100%
ARN6B LDAB PWMP1P
MUL PWMP1P * adjusted duty cycle = OFFOCx
RTS ** Return from CALOFF **
*
**
***
* SV6OC1 - Output Compare 1 service routine
***
SV6OC1 LDX #REGBAS Point to register block
LDAA OC1D,X Make PA4 change state at next OC1 compare
EORA #%00010000 Inverts OC1D4 bit (PA4 pin control)
STAA OC1D,X Update next OC1 automatic pattern
LDD TOC2,X Get last OC2 compare value
ADDD PWMPER Add count equiv to period
STD TOC2,X Update OC2 (schedule next OC2)
LDD TOC3,X Get last OC3 compare value
ADDD PWMPER Add count equiv to period
STD TOC3,X Update OC3 (schedule next OC3)
LDD TOC1,X Get last OC1 compare value
ADDD PWMPER Add count equiv to period
STD TOC1,X Update OC1 (schedule next OC1)
BCLR TFLG1,X $7F Clear OC1F
RTI ** Return from OC1 service **
*
***** END Ex 10-6
***
* TIMER EXAMPLE 10-7
* OC2 used alone to produce one PWM signal
*
* OC2 controls period and duty cycle of one port A pin
* Set "PWMP1P" & "PWMDC1" manually before running this example
* "PWMP1P" sets size of a 1% segment of PWM period (cycles)
* "PWMDC1" sets Duty cycle for OC2 pin in % - NOTE: This program will
* not work properly with values of duty cycle too near 0 or 100%
* Refer to User's Manual text for discussions
* Program calculates "OFFHI" and "OFFLO" at start
*
* This program runs on an EVB board and drives the PA6/OC2 pin.
* An oscilloscope is used to study the results.
***
INZ7 LDS #$0047 Top of User's stack area on EVB
LDAA #$7E Jump (extended) Opcode
STAA PVOC2 OC2 Pseudo Vector
LDX #SV7OC2 Address of OC2 service routine
STX PVOC2+1 Finish jump instruc to OC2 routine
LDX #REGBAS Point to register block
LDAA PWMDC1 Calculate OC2 high time
LDAB PWMP1P 1% of period
MUL PWMP1P * duty cycle = high part of period
STD OFFHI Save high offset
LDAA PWMP1P 1% of period
LDAB #100
MUL 100 * PWMP1P = period
SUBD OFFHI period - high time = low time
STD OFFLO Store low offset
* Finish initialization
LDAA #%11000000 OM2:OM1 = 1:1 for set pin high
STAA TCTL1,X First OC2 starts first high time
LDD #$0000
STD TOC2,X Start first PWM period at TCNT=$0000
LDAA #$40
STAA TFLG1,X OC2F=1 to clear any old OC2 flag
STAA TMSK1,X then OC2I=1 to enable OC2 interrupt
CLI
BRA * From now on OC2 interrupt runs PWM
***
* SV7OC2 - Output Compare 2 service routine
***
SV7OC2 LDX #REGBAS Point to register block
BRCLR TCTL1,X %01000000 ADDLO See which half of cyc
LDD OFFHI High part so we will add OFFHI to OC2
BRA UPOC2
ADDLO LDD OFFLO Low part so we will add OFFLO to OC2
UPOC2 ADDD TOC2,X Add to last compare value
STD TOC2,X Update OC2 (schedule next edge)
LDAA TCTL1,X Change OL2 to setup for next edge
EORA #%01000000 Inverts OL2 bit
STAA TCTL1,X Update control reg
BCLR TFLG1,X $BF Clear OC2F
RTI ** Return from OC2 service **
*
***** END Ex 10-7
***
* General purpose subroutines
***
***
* P5DEC - Subroutine to display a five digit decimal number at "DBUFR".
* Prints in the form "xx,xxx" with leading zeros suppressed.
* Prints 6 columns, leading spaces, units always prints (0-9)
*
* Calls EVB routine ".OUTA"
* Calls "SKP1" with BSR to advance X and print a leading space
* SKP1 subroutine immediately follows P5DEC
* All registers are unchanged upon return from P5DEC
***
P5DEC PSHX Save registers
PSHB
PSHA
LDX #DBUFR Point at decimal (MS character)
LDAA #$30 Chk for leading 0s (ASCII)
CMPA 0,X Check 10,000s digit
BNE P10K Start at 10k digit
BSR SKP1 INX & print a space
CMPA 0,X Check 1,000s digit (a still=ASCII<sp>)
BNE P1K Start at 1k digit
BSR SKP1 INX & print a space
BSR SKP1 INX & print a space (extra 1 for ,)
DEX just wanted the <sp> so back up 1
CMPA 0,X Check 100s digit
BNE P100 Start at 100s digit
BSR SKP1 INX & print a space
CMPA 0,X Check 10s digit
BNE P10 Start at 10s digit
BSR SKP1 INX & print a space
BRA P1 Start at 1s digit (default)
P10K LDAA 0,X 10,000s digit
JSR .OUTA Print 10,000s digit
INX Advance pointer to next digt
P1K LDAA 0,X 1,000s digit
JSR .OUTA Print it
LDAA #',' ASCII comma
JSR .OUTA Print
INX Advance pointer to next digt
P100 LDAA 0,X 100s digit
JSR .OUTA Print it
INX Advance pointer to next digt
P10 LDAA 0,X 10s digit
JSR .OUTA Print it
INX Advance pointer to next digt
P1 LDAA 0,X 1s digit
JSR .OUTA Print it
PULA Restore registers
PULB
PULX
RTS ** Return from P5DEC **
*** Local SKP1 subroutine (called from above with BSRs)
SKP1 PSHA Save A
INX Advance X
LDAA #$20 ASCII <sp>
JSR .OUTA Print the <sp>
PULA Restore A
RTS ** Return from SKP1 **
***
* HTOD - Subroutine to convert a 16-bit hex number to a
* 5 digit decimal number.
*
* Uses 5 byte variable "DBUFR" for decimal ASCII result
* On entry X points to hex value to be converted & displayed
* All registers are unchanged upon return
***
HTOD PSHX Save registers
PSHB
PSHA
LDD 0,X D=hex value to be converted
LDX #10000
IDIV freq╓10,000 -> X; r -> D
XGDX Save r in X; 10,000s digit in D (A:B)
ADDB #$30 Convert to ASCII
STAB DBUFR Store in decimal buffer
XGDX r back to D
LDX #1000
IDIV r╓1,000 -> X; r -> D
XGDX Save r in X; 1,000s digit in D (A:B)
ADDB #$30 Convert to ASCII
STAB DBUFR+1 Store in decimal buffer
XGDX r back to D
LDX #100
IDIV r╓100 -> X; r -> D
XGDX Save r in X; 100s digit in D (A:B)
ADDB #$30 Convert to ASCII
STAB DBUFR+2 Store in decimal buffer
XGDX r back to D
LDX #10
IDIV r╓10 -> X; r in D (B is units digit)
ADDB #$30 Convert to ASCII
STAB DBUFR+4 Store to units digit
XGDX 10s digit to D (A:B)
ADDB #$30 Convert to ASCII
STAB DBUFR+3 Store in decimal buffer
PULA Restore registers
PULB
PULX
RTS ** Return **
***
* H6TOD8 - Subroutine to convert a 24-bit hex number to an
* 8 digit decimal number.
*
* Uses 3 byte variable "HTEMP" for hex working value
* Uses 8 byte variable "DBUFR" for decimal ASCII result
* On entry X points to hex value to be converted & displayed
* All registers are unchanged upon return
***
H6TOD8 PSHY Save registers
PSHX
PSHB
PSHA
LDD 1,X Move hex to HTEMP for conversion
STD HTEMP+1 Two lower bytes moved
LDAA 0,X Upper byte
STAA HTEMP
LDY #DBUFR Point at MS digit of decimal buffer
LDX #CON10M Point at first 24-bit constant
HTDLP CLRA A keeps track of # of subtractions
HLPIN INCA Inner loop; once per subtraction
LDAB HTEMP+2 Start 24-bit subtract
SUBB 2,X
STAB HTEMP+2 Update low byte
LDAB HTEMP+1 Middle byte
SBCB 1,X Sub with carry
STAB HTEMP+1 Update middle byte
LDAB HTEMP High byte
SBCB 0,X
STAB HTEMP Update high byte
BCC HLPIN If no borrow; subtract again
LDAB HTEMP+2 Last subtract too far; add back
ADDB 2,X
STAB HTEMP+2 Update low byte
LDAB HTEMP+1 Middle byte
ADCB 1,X Sub with carry
STAB HTEMP+1 Update middle byte
LDAB HTEMP High byte
ADCB 0,X
STAB HTEMP Update high byte
ADDA #$2F Convert digit to ASCII
STAA 0,Y Store to decimal buffer
INY Point to next decimal digit
INX Point to next 24-bit const
INX
INX
CPX #CONEND See if done yet
BNE HTDLP If not done, do nxt digit
LDAA HTEMP+2 Get 1s digit
ADDA #$30 Convert to ASCII
STAA 0,Y Store to last decimal digit
PULA Restore registers
PULB
PULX
PULY
RTS ** Return from H6TOD8 **
*
* Display Messages & Constants
*
MSGCYC FCC ' Cycles '
FCB $04 End-of-message mark
MSGHZ FCC ' Hz'
FCB $04 End-of-message mark
MSGER1 FCC 'Freq. is too high'
FCB $04 End-of-message mark
MSGMS FCC ' microseconds'
FCB $04 End-of-message mark
MSGSEC FCC ' Seconds'
FCB $04 End-of-message mark
CON10M FCB $98,$96,$80 = 24-bit equiv of 10,000,000
FCB $0F,$42,$40 = 24-bit equiv of 1,000,000
FCB $01,$86,$A0 = 24-bit equiv of 100,000
FCB $00,$27,$10 = 24-bit equiv of 10,000
FCB $00,$03,$E8 = 24-bit equiv of 1,000
FCB $00,$00,$64 = 24-bit equiv of 100
FCB $00,$00,$0A = 24-bit equiv of 10
CONEND EQU * Don't need 1s const
* END OF FILE